<ui:composition xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:fn="http://java.sun.com/jsp/jstl/functions"
        xmlns:g="http://code.google.com/p/ada-ado/generator"
        xmlns:f="http://java.sun.com/jsf/core">
<h:list value="#{package.tables}" var="table">
   function #{table.type}_Key (Id : in ADO.Identifier) return ADO.Objects.Object_Key is
      Result : ADO.Objects.Object_Key (Of_Type  => ADO.Objects.#{g:keyEnum(table.id.type)},
                                       Of_Class => #{fn:toUpperCase(table.type)}_TABLE'Access);
   begin
      ADO.Objects.Set_Value (Result, Id);
      return Result;
   end #{table.type}_Key;

   function #{table.type}_Key (Id : in String) return ADO.Objects.Object_Key is
      Result : ADO.Objects.Object_Key (Of_Type  => ADO.Objects.#{g:keyEnum(table.id.type)},
                                       Of_Class => #{fn:toUpperCase(table.type)}_TABLE'Access);
   begin
      ADO.Objects.Set_Value (Result, Id);
      return Result;
   end #{table.type}_Key;

   function "=" (Left, Right : #{table.type}_Ref'Class) return Boolean is
   begin
      return ADO.Objects.Object_Ref'Class (Left) = ADO.Objects.Object_Ref'Class (Right);
   end "=";

   procedure Set_Field (Object : in out #{fn:capitalize(table.type)}_Ref'Class;
                        Impl   : out #{fn:capitalize(table.type)}_Access;
                        Field  : in Positive) is
   begin
      Object.Set_Field (Field);
      Impl := #{fn:capitalize(table.type)}_Impl (Object.Get_Object.all)'Access;
   end Set_Field;

   --  Internal method to allocate the Object_Record instance
   procedure Allocate (Object : in out #{fn:capitalize(table.type)}_Ref) is
      Impl : #{fn:capitalize(table.type)}_Access;
   begin
      Impl := new #{fn:capitalize(table.type)}_Impl;
<h:list value="#{table.members}" var="column">
  <h:panelGroup rendered="#{column.name ne table.id.name and column.type.isIdentifier}">
      Impl.#{fn:capitalize(column.name)} := ADO.NO_IDENTIFIER;
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isBoolean}">
      Impl.#{fn:capitalize(column.name)} := False;
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isInteger}">
      Impl.#{fn:capitalize(column.name)} := 0;
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isDate and g:adaType(column,1) eq 'ADO.Nullable_Time'}">
      Impl.#{fn:capitalize(column.name)}.Is_Null := True;
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isDate and g:adaType(column,1) ne 'ADO.Nullable_Time'}">
      Impl.#{fn:capitalize(column.name)} := ADO.DEFAULT_TIME;
  </h:panelGroup>
</h:list>
      ADO.Objects.Set_Object (Object, Impl.all'Access);
   end Allocate;
#{''}
   -- ----------------------------------------
   --  Data object: #{fn:capitalize(table.type)}
   -- ----------------------------------------
<h:list value="#{table.members}" var="column">
  <h:panelGroup rendered="#{column.isInserted or column.isUpdated}">
    <h:panelGroup rendered="#{column.type.isString}">
   procedure Set_#{fn:capitalize(column.name)} (Object : in out #{fn:capitalize(table.type)}_Ref;
                   #{g:indent(column.name)} Value : in String) is
   begin
      Object.Set_#{fn:capitalize(column.name)} (Ada.Strings.Unbounded.To_Unbounded_String (Value));
   end Set_#{fn:capitalize(column.name)};
    </h:panelGroup>

   procedure Set_#{fn:capitalize(column.name)} (Object : in out #{fn:capitalize(table.type)}_Ref;
                   #{g:indent(column.name)} Value  : in #{g:adaType(column,1)}) is
      Impl : #{fn:capitalize(table.type)}_Access;
   begin
      Set_Field (Object, Impl, #{column.index + 1});
    <h:panelGroup rendered="#{column.name ne table.id.name and column.type.isBoolean}">
      Impl.#{fn:capitalize(column.name)} := Value;
    </h:panelGroup>
    <h:panelGroup rendered="#{column.name ne table.id.name and not column.isPrimitiveType and not column.type.isBoolean}">
      Impl.#{fn:capitalize(column.name)} := #{g:adaType(column,0)} (Value);
    </h:panelGroup>
    <h:panelGroup rendered="#{column.name ne table.id.name and column.isPrimitiveType}">
      Impl.#{fn:capitalize(column.name)} := Value;
    </h:panelGroup>
    <h:panelGroup rendered="#{column.name eq table.id.name}">
      ADO.Objects.Set_Key_Value (Impl.all, Value);
    </h:panelGroup>
   end Set_#{fn:capitalize(column.name)};
  </h:panelGroup>

  <h:panelGroup rendered="#{column.isReadable}">
    <h:panelGroup rendered="#{column.type.isString}">
   function Get_#{fn:capitalize(column.name)} (Object : in #{fn:capitalize(table.type)}_Ref)
                 return String is
   begin
      return Ada.Strings.Unbounded.To_String (Object.Get_#{fn:capitalize(column.name)});
   end Get_#{fn:capitalize(column.name)};
    </h:panelGroup>

   function Get_#{fn:capitalize(column.name)} (Object : in #{fn:capitalize(table.type)}_Ref)
                  return #{g:adaType(column,1)} is
    <h:panelGroup rendered="#{column.name ne table.id.name}">
      Impl : constant #{fn:capitalize(table.type)}_Access := #{fn:capitalize(table.type)}_Impl (Object.Get_Load_Object.all)'Access;
   begin
      return Impl.#{fn:capitalize(column.name)};
    </h:panelGroup>
    <h:panelGroup rendered="#{column.name eq table.id.name}">
      Impl : constant #{fn:capitalize(table.type)}_Access := #{fn:capitalize(table.type)}_Impl (Object.Get_Object.all)'Access;
   begin
      return Impl.Get_Key_Value;
    </h:panelGroup>
   end Get_#{fn:capitalize(column.name)};
  </h:panelGroup>
</h:list>

   --  Copy of the object.
   function Copy (Object : #{fn:capitalize(table.type)}_Ref) return #{fn:capitalize(table.type)}_Ref is
      Result : #{fn:capitalize(table.type)}_Ref;
   begin
      if not Object.Is_Null then
         declare
            Impl : constant #{fn:capitalize(table.type)}_Access
              := #{fn:capitalize(table.type)}_Impl (Object.Get_Load_Object.all)'Access;
            Copy : constant #{fn:capitalize(table.type)}_Access
              := new #{fn:capitalize(table.type)}_Impl;
         begin
            ADO.Objects.Set_Object (Result, Copy.all'Access);
            Copy.Copy (Impl.all);
<h:list value="#{table.members}" var="column">
<h:panelGroup rendered="#{column.name ne table.id.name}">
            Copy.#{fn:capitalize(column.name)} := Impl.#{fn:capitalize(column.name)};
</h:panelGroup>
<h:panelGroup rendered="#{column.name eq table.id.name and (table.id.generator eq 'none')}">
            Copy.all.Set_Key (Impl.all.Get_Key);
</h:panelGroup>
</h:list>
         end;
      end if;
      return Result;
   end Copy;

   procedure Find (Object  : in out #{fn:capitalize(table.type)}_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Query   : in ADO.SQL.Query'Class;
                   Found   : out Boolean) is
      Impl  : constant #{fn:capitalize(table.type)}_Access := new #{fn:capitalize(table.type)}_Impl;
   begin
      Impl.Find (Session, Query, Found);
      if Found then
         ADO.Objects.Set_Object (Object, Impl.all'Access);
      else
         ADO.Objects.Set_Object (Object, null);
         Destroy (Impl);
      end if;
   end Find;

   procedure Load (Object  : in out #{fn:capitalize(table.type)}_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Id      : in #{g:adaType(table.id,0)}) is
      Impl  : constant #{fn:capitalize(table.type)}_Access := new #{fn:capitalize(table.type)}_Impl;
      Found : Boolean;
      Query : ADO.SQL.Query;
   begin
      Query.Bind_Param (Position => 1, Value => Id);
      Query.Set_Filter ("#{table.id.name} = ?");
      Impl.Find (Session, Query, Found);
      if not Found then
         Destroy (Impl);
         raise ADO.Objects.NOT_FOUND;
      end if;
      ADO.Objects.Set_Object (Object, Impl.all'Access);
   end Load;

   procedure Load (Object  : in out #{fn:capitalize(table.type)}_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Id      : in #{g:adaType(table.id,0)};
                   Found   : out Boolean) is
      Impl  : constant #{fn:capitalize(table.type)}_Access := new #{fn:capitalize(table.type)}_Impl;
      Query : ADO.SQL.Query;
   begin
      Query.Bind_Param (Position => 1, Value => Id);
      Query.Set_Filter ("#{table.id.name} = ?");
      Impl.Find (Session, Query, Found);
      if not Found then
         Destroy (Impl);
      else
         ADO.Objects.Set_Object (Object, Impl.all'Access);
      end if;
   end Load;

   procedure Save (Object  : in out #{fn:capitalize(table.type)}_Ref;
                   Session : in out ADO.Sessions.Master_Session'Class) is
      Impl : ADO.Objects.Object_Record_Access := Object.Get_Object;
   begin
      if Impl = null then
         Impl := new #{fn:capitalize(table.type)}_Impl;
         ADO.Objects.Set_Object (Object, Impl);
      end if;
      if not ADO.Objects.Is_Created (Impl.all) then
         Impl.Create (Session);
      else
         Impl.Save (Session);
      end if;
   end Save;

   procedure Delete (Object  : in out #{fn:capitalize(table.type)}_Ref;
                     Session : in out ADO.Sessions.Master_Session'Class) is
      Impl : constant ADO.Objects.Object_Record_Access := Object.Get_Object;
   begin
      if Impl /= null then
         Impl.Delete (Session);
      end if;
   end Delete;

   --  --------------------
   --  Free the object
   --  --------------------
   procedure Destroy (Object : access #{fn:capitalize(table.type)}_Impl) is
      type #{fn:capitalize(table.type)}_Impl_Ptr is access all #{fn:capitalize(table.type)}_Impl;

      procedure Unchecked_Free is new Ada.Unchecked_Deallocation
              (#{fn:capitalize(table.type)}_Impl, #{fn:capitalize(table.type)}_Impl_Ptr);

      Ptr : #{fn:capitalize(table.type)}_Impl_Ptr := #{fn:capitalize(table.type)}_Impl (Object.all)'Access;
   begin
      Unchecked_Free (Ptr);
   end Destroy;

   procedure Find (Object  : in out #{fn:capitalize(table.type)}_Impl;
                   Session : in out ADO.Sessions.Session'Class;
                   Query   : in ADO.SQL.Query'Class;
                   Found   : out Boolean) is
      Stmt : ADO.Statements.Query_Statement
          := Session.Create_Statement (#{fn:toUpperCase(table.type)}_TABLE'Access);
   begin
      Stmt.Set_Parameters (Query);
      Stmt.Execute;
      if Stmt.Has_Elements then
         Object.Load (Stmt, Session);
         Stmt.Next;
         Found := not Stmt.Has_Elements;
      else
         Found := False;
      end if;
   end Find;

   overriding
   procedure Load (Object  : in out #{fn:capitalize(table.type)}_Impl;
                   Session : in out ADO.Sessions.Session'Class) is
      Found : Boolean;
      Query : ADO.SQL.Query;
      Id    : constant #{g:adaType(table.id,0)} := Object.Get_Key_Value;
   begin
      Query.Bind_Param (Position => 1, Value => Id);
      Query.Set_Filter ("#{table.id.name} = ?");
      Object.Find (Session, Query, Found);
      if not Found then
         raise ADO.Objects.NOT_FOUND;
      end if;
   end Load;

   procedure Save (Object  : in out #{fn:capitalize(table.type)}_Impl;
                   Session : in out ADO.Sessions.Master_Session'Class) is
      Stmt : ADO.Statements.Update_Statement
         := Session.Create_Statement (#{fn:toUpperCase(table.type)}_TABLE'Access);
   begin
<h:list value="#{table.members}" var="column">
    <h:panelGroup rendered="#{column.isUpdated}">
      if Object.Is_Modified (#{column.index + 1}) then
      <h:panelGroup rendered="#{column.name ne table.id.name}">
         Stmt.Save_Field (Name  => COL_#{column.index}_#{package.tables.rowIndex}_NAME, --  #{column.sqlName}
                          Value => Object.#{fn:capitalize(column.name)});
      </h:panelGroup>
      <h:panelGroup rendered="#{column.name eq table.id.name}">
         Stmt.Save_Field (Name  => COL_#{column.index}_#{package.tables.rowIndex}_NAME, --  #{column.sqlName}
                          Value => Object.Get_Key);
      </h:panelGroup>
         Object.Clear_Modified (#{column.index + 1});
      end if;
    </h:panelGroup>
</h:list>
      if Stmt.Has_Save_Fields then
<h:panelGroup rendered="#{not empty table.version}">
         Object.#{fn:capitalize(table.version.name)} := Object.#{fn:capitalize(table.version.name)} + 1;
         Stmt.Save_Field (Name  => "#{table.version.name}",
                          Value => Object.#{fn:capitalize(table.version.name)});
         Stmt.Set_Filter (Filter => "#{table.id.name} = ? and #{table.version.name} = ?");
         Stmt.Add_Param (Value => Object.Get_Key);
         Stmt.Add_Param (Value => Object.#{fn:capitalize(table.version.name)} - 1);
</h:panelGroup>
<h:panelGroup rendered="#{empty table.version}">
         Stmt.Set_Filter (Filter => "#{table.id.name} = ?");
         Stmt.Add_Param (Value => Object.Get_Key);
</h:panelGroup>
         declare
            Result : Integer;
         begin
            Stmt.Execute (Result);
            if Result /= 1 then
               if Result = 0 then
                  raise ADO.Objects.LAZY_LOCK;
               else
                  raise ADO.Objects.UPDATE_ERROR;
               end if;
            end if;
         end;
      end if;
   end Save;

   procedure Create (Object  : in out #{fn:capitalize(table.type)}_Impl;
                     Session : in out ADO.Sessions.Master_Session'Class) is
      Query : ADO.Statements.Insert_Statement
                  := Session.Create_Statement (#{fn:toUpperCase(table.type)}_TABLE'Access);
      Result : Integer;
   begin
<h:panelGroup rendered="#{not empty table.version}">
      Object.#{fn:capitalize(table.version.name)} := 1;
</h:panelGroup>
<h:list value="#{table.members}" var="column">
  <h:panelGroup rendered="#{table.id.generator ne 'native' and table.id.name eq column.name and table.id.generator ne 'none'}">
      Session.Allocate (Id => Object);
  </h:panelGroup>
  <h:panelGroup rendered="#{table.id.generator ne 'native' or table.id.name ne column.name}">
    <h:panelGroup rendered="#{column.name ne table.id.name and (column.isInserted or column.isVersion)}">
      Query.Save_Field (Name  => COL_#{column.index}_#{package.tables.rowIndex}_NAME, --  #{column.sqlName}
                        Value => Object.#{fn:capitalize(column.name)});
    </h:panelGroup>
    <h:panelGroup rendered="#{column.name eq table.id.name}">
      Query.Save_Field (Name  => COL_#{column.index}_#{package.tables.rowIndex}_NAME, --  #{column.sqlName}
                        Value => Object.Get_Key);
    </h:panelGroup>
  </h:panelGroup>
</h:list>
<h:panelGroup rendered="#{table.id.generator ne 'native'}">
      Query.Execute (Result);
      if Result /= 1 then
         raise ADO.Objects.INSERT_ERROR;
      end if;
</h:panelGroup>
<h:panelGroup rendered="#{table.id.generator eq 'native'}">
      Query.Execute (Object.#{fn:capitalize(table.id.name)});
</h:panelGroup>
      ADO.Objects.Set_Created (Object);
   end Create;

   procedure Delete (Object  : in out #{fn:capitalize(table.type)}_Impl;
                     Session : in out ADO.Sessions.Master_Session'Class) is
      Stmt : ADO.Statements.Delete_Statement
         := Session.Create_Statement (#{fn:toUpperCase(table.type)}_TABLE'Access);
   begin
      Stmt.Set_Filter (Filter => "#{table.id.name} = ?");
      Stmt.Add_Param (Value => Object.Get_Key);
      Stmt.Execute;
   end Delete;

   function Get_Value (Item : in #{fn:capitalize(table.type)}_Ref;
                       Name : in String) return Util.Beans.Objects.Object is
      Impl : constant access #{fn:capitalize(table.type)}_Impl
         := #{fn:capitalize(table.type)}_Impl (Item.Get_Load_Object.all)'Access;
   begin
<h:list value="#{table.members}" var="column">
  <h:panelGroup rendered="#{not column.isVersion and column.isPrimitiveType}">
      if Name = "#{column.name}" then
    <h:panelGroup rendered="#{column.name eq table.id.name}">
         return ADO.Objects.To_Object (Impl.Get_Key);
    </h:panelGroup>
    <h:panelGroup rendered="#{column.name ne table.id.name}">
      <h:panelGroup rendered="#{column.type.isInteger or column.type.isIdentifier}">
         return Util.Beans.Objects.To_Object (Long_Long_Integer (Impl.#{fn:capitalize(column.name)}));
      </h:panelGroup>
      <h:panelGroup rendered="#{column.type.isDate and g:adaType(column,1) ne 'ADO.Nullable_Time'}">
         return Util.Beans.Objects.Time.To_Object (Impl.#{fn:capitalize(column.name)});
      </h:panelGroup>
      <h:panelGroup rendered="#{column.type.isDate and g:adaType(column,1) eq 'ADO.Nullable_Time'}">
         if Impl.#{fn:capitalize(column.name)}.Is_Null then
            return Util.Beans.Objects.Null_Object;
         else
            return Util.Beans.Objects.Time.To_Object (Impl.#{fn:capitalize(column.name)}.Value);
         end if;
      </h:panelGroup>
    <h:panelGroup rendered="#{not column.type.isInteger and not column.type.isIdentifier and not column.type.isDate}">
         return Util.Beans.Objects.To_Object (Impl.#{fn:capitalize(column.name)});
  </h:panelGroup>
</h:panelGroup>
      end if;
</h:panelGroup></h:list>
      raise ADO.Objects.NOT_FOUND;
   end Get_Value;

   procedure List (Object  : in out #{fn:capitalize(table.type)}_Vector;
                   Session : in out ADO.Sessions.Session'Class;
                   Query   : in ADO.SQL.Query'Class) is
      Stmt : ADO.Statements.Query_Statement := Session.Create_Statement (#{fn:toUpperCase(table.type)}_TABLE'Access);
   begin
      Stmt.Set_Parameters (Query);
      Stmt.Execute;
      #{fn:capitalize(table.type)}_Vectors.Clear (Object);
      while Stmt.Has_Elements loop
         declare
            Item : #{fn:capitalize(table.type)}_Ref;
            Impl : constant #{fn:capitalize(table.type)}_Access := new #{fn:capitalize(table.type)}_Impl;
         begin
            Impl.Load (Stmt, Session);
            ADO.Objects.Set_Object (Item, Impl.all'Access);
            Object.Append (Item);
         end;
         Stmt.Next;
      end loop;
   end List;

   --  ------------------------------
   --  Load the object from current iterator position
   --  ------------------------------
   procedure Load (Object  : in out #{fn:capitalize(table.type)}_Impl;
                   Stmt    : in out ADO.Statements.Query_Statement'Class;
                   Session : in out ADO.Sessions.Session'Class) is
<h:panelGroup rendered="#{not table.hasAssociations}">
      pragma Unreferenced (Session);
</h:panelGroup>
   begin
<h:list value="#{table.members}" var="column">

  <h:panelGroup rendered="#{column.name eq table.id.name and column.type.isIdentifier}">
      Object.Set_Key_Value (Stmt.Get_Identifier (#{column.index}));
  </h:panelGroup>

  <h:panelGroup rendered="#{column.name eq table.id.name and not column.type.isIdentifier}">
      Object.Set_Key_Value (Stmt.Get_Unbounded_String (#{column.index}));
  </h:panelGroup>

<h:panelGroup rendered="#{column.name ne table.id.name and column.name ne table.version.name}">
  <h:panelGroup rendered="#{not column.isPrimitiveType and not column.type.isBoolean}">
      if not Stmt.Is_Null (#{column.index}) then
          Object.#{fn:capitalize(column.name)}.Set_Key_Value (Stmt.Get_Identifier (#{column.index}), Session);
      end if;
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isIdentifier}">
      Object.#{fn:capitalize(column.name)} := Stmt.Get_Identifier (#{column.index});
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isString}">
      Object.#{fn:capitalize(column.name)} := Stmt.Get_Unbounded_String (#{column.index});
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isBoolean}">
      Object.#{fn:capitalize(column.name)} := Stmt.Get_Boolean (#{column.index});
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.isDate}">
      Object.#{fn:capitalize(column.name)} := Stmt.Get_Time (#{column.index});
  </h:panelGroup>
  <h:panelGroup rendered="#{column.type.name eq 'ADO.Entity_Type'}">
      Object.#{fn:capitalize(column.name)} := ADO.Entity_Type (Stmt.Get_Integer (#{column.index}));
  </h:panelGroup>
  <h:panelGroup rendered="#{column.isPrimitiveType and not column.type.isIdentifier and not column.type.isString and not column.type.name eq 'ADO.Entity_Type'}">
      Object.#{fn:capitalize(column.name)} := Stmt.Get_#{fn:capitalize(g:adaType(column,2))} (#{column.index});
  </h:panelGroup>
</h:panelGroup>
</h:list>
<h:panelGroup rendered="#{not empty table.version}">
      Object.#{fn:capitalize(table.version.name)} := Stmt.Get_#{fn:capitalize(g:adaType(table.version,0))} (#{table.version.index});
</h:panelGroup>
      ADO.Objects.Set_Created (Object);
   end Load;
</h:list>
</ui:composition>
